﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;


#if WINDOWS_PHONE_APP

    /// <summary>
    /// ContinuationManager is used to detect if the most recent activation was due
    /// to a continuation such as the FileOpenPicker or WebAuthenticationBroker
    /// </summary>
    public class ContinuationManager
    {
        IContinuationActivatedEventArgs args = null;
        bool handled = false;
        Guid id = Guid.Empty;

        ///// <summary>
        ///// Sets the ContinuationArgs for this instance. Using default Frame of current Window
        ///// Should be called by the main activation handling code in App.xaml.cs
        ///// </summary>
        ///// <param name="args">The activation args</param>
        //internal void Continue(IContinuationActivatedEventArgs args)
        //{
        //    Continue(args, Window.Current.Content as Frame);
        //}

        ///// <summary>
        ///// Sets the ContinuationArgs for this instance. Should be called by the main activation
        ///// handling code in App.xaml.cs
        ///// </summary>
        ///// <param name="args">The activation args</param>
        ///// <param name="rootFrame">The frame control that contains the current page</param>
        //internal void Continue(IContinuationActivatedEventArgs args, Frame rootFrame)
        //{
        //    if (args == null)
        //        throw new ArgumentNullException("args");

        //    if (this.args != null && !handled)
        //        throw new InvalidOperationException("Can't set args more than once");

        //    this.args = args;
        //    this.handled = false;
        //    this.id = Guid.NewGuid();

        //    if (rootFrame == null)
        //        return;

        //    switch (args.Kind)
        //    {
        //        case ActivationKind.PickFileContinuation:
        //            var fileOpenPickerPage = rootFrame.Content as IFileOpenPickerContinuable;
        //            if (fileOpenPickerPage != null)
        //            {
        //                fileOpenPickerPage.ContinueFileOpenPicker(args as FileOpenPickerContinuationEventArgs);
        //            }
        //            break;

        //        case ActivationKind.PickSaveFileContinuation:
        //            var fileSavePickerPage = rootFrame.Content as IFileSavePickerContinuable;
        //            if (fileSavePickerPage != null)
        //            {
        //                fileSavePickerPage.ContinueFileSavePicker(args as FileSavePickerContinuationEventArgs);
        //            }
        //            break;

        //        case ActivationKind.PickFolderContinuation:
        //            var folderPickerPage = rootFrame.Content as IFolderPickerContinuable;
        //            if (folderPickerPage != null)
        //            {
        //                folderPickerPage.ContinueFolderPicker(args as FolderPickerContinuationEventArgs);
        //            }
        //            break;

        //        case ActivationKind.WebAuthenticationBrokerContinuation:
        //            var wabPage = rootFrame.Content as IWebAuthenticationContinuable;
        //            if (wabPage != null)
        //            {
        //                wabPage.ContinueWebAuthentication(args as WebAuthenticationBrokerContinuationEventArgs);
        //            }
        //            break;
        //    }
        //}
        private FrameworkElement GetCurrentView()
        {
            var frame = Window.Current.Content as Frame;
            if (frame != null)
                return frame.Content as FrameworkElement;

            return Window.Current.Content as FrameworkElement;
        }

        internal void Continue(IContinuationActivatedEventArgs args)
        {
            var view = this.GetCurrentView();
            if (view == null)
                return;

            this.Continue(args, view.DataContext);
        }

        internal void Continue(IContinuationActivatedEventArgs args, object dataContext)
        {
            if (args == null)
                throw new ArgumentNullException("args");

            if (this.args != null)
                throw new InvalidOperationException("Can't set args more than once");

            this.args = args;
            this.id = Guid.NewGuid();

            if (dataContext == null)
                return;

            switch (args.Kind)
            {
                case ActivationKind.PickFileContinuation:
                    var fileOpenPickerViewModel = dataContext as IFileOpenPickerContinuable;
                    if (fileOpenPickerViewModel != null)
                        fileOpenPickerViewModel.ContinueFileOpenPicker
                            (args as FileOpenPickerContinuationEventArgs);
                    break;

                case ActivationKind.PickSaveFileContinuation:
                    var fileSavePickerViewModel = dataContext as IFileSavePickerContinuable;
                    if (fileSavePickerViewModel != null)
                        fileSavePickerViewModel.ContinueFileSavePicker
                            (args as FileSavePickerContinuationEventArgs);
                    break;

                case ActivationKind.PickFolderContinuation:
                    var folderPickerViewModel = dataContext as IFolderPickerContinuable;
                    if (folderPickerViewModel != null)
                        folderPickerViewModel.ContinueFolderPicker
                            (args as FolderPickerContinuationEventArgs);
                    break;

                case ActivationKind.WebAuthenticationBrokerContinuation:
                    var wabViewModel = dataContext as IWebAuthenticationContinuable;
                    if (wabViewModel != null)
                        wabViewModel.ContinueWebAuthentication
                            (args as WebAuthenticationBrokerContinuationEventArgs);
                    break;
            }
        }
        /// <summary>
        /// Marks the contination data as 'stale', meaning that it is probably no longer of
        /// any use. Called when the app is suspended (to ensure future activations don't appear
        /// to be for the same continuation) and whenever the continuation data is retrieved 
        /// (so that it isn't retrieved on subsequent navigations)
        /// </summary>
        internal void MarkAsStale()
        {
            this.handled = true;
        }

        /// <summary>
        /// Retrieves the continuation args, if they have not already been retrieved, and 
        /// prevents further retrieval via this property (to avoid accidentla double-usage)
        /// </summary>
        public IContinuationActivatedEventArgs ContinuationArgs
        {
            get
            {
                if (handled)
                    return null;
                MarkAsStale();
                return args;
            }
        }

        /// <summary>
        /// Unique identifier for this particular continuation. Most useful for components that 
        /// retrieve the continuation data via <see cref="GetContinuationArgs"/> and need
        /// to perform their own replay check
        /// </summary>
        public Guid Id { get { return id; } }

        /// <summary>
        /// Retrieves the continuation args, optionally retrieving them even if they have already
        /// been retrieved
        /// </summary>
        /// <param name="includeStaleArgs">Set to true to return args even if they have previously been returned</param>
        /// <returns>The continuation args, or null if there aren't any</returns>
        public IContinuationActivatedEventArgs GetContinuationArgs(bool includeStaleArgs)
        {
            if (!includeStaleArgs && handled)
                return null;
            MarkAsStale();
            return args;
        }
    }

    /// <summary>
    /// Implement this interface if your page invokes the file open picker
    /// API.
    /// </summary>
    interface IFileOpenPickerContinuable
    {
        /// <summary>
        /// This method is invoked when the file open picker returns picked
        /// files
        /// </summary>
        /// <param name="args">Activated event args object that contains returned files from file open picker</param>
        void ContinueFileOpenPicker(FileOpenPickerContinuationEventArgs args);
    }

    /// <summary>
    /// Implement this interface if your page invokes the file save picker
    /// API
    /// </summary>
    interface IFileSavePickerContinuable
    {
        /// <summary>
        /// This method is invoked when the file save picker returns saved
        /// files
        /// </summary>
        /// <param name="args">Activated event args object that contains returned file from file save picker</param>
        void ContinueFileSavePicker(FileSavePickerContinuationEventArgs args);
    }

    /// <summary>
    /// Implement this interface if your page invokes the folder picker API
    /// </summary>
    interface IFolderPickerContinuable
    {
        /// <summary>
        /// This method is invoked when the folder picker returns the picked
        /// folder
        /// </summary>
        /// <param name="args">Activated event args object that contains returned folder from folder picker</param>
        void ContinueFolderPicker(FolderPickerContinuationEventArgs args);
    }

    /// <summary>
    /// Implement this interface if your page invokes the web authentication
    /// broker
    /// </summary>
    interface IWebAuthenticationContinuable
    {
        /// <summary>
        /// This method is invoked when the web authentication broker returns
        /// with the authentication result
        /// </summary>
        /// <param name="args">Activated event args object that contains returned authentication token</param>
        void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args);
    }

#endif

